// symbol的值是通过Symbol构造函数创建的
let sym1 = Symbol()
let sym2 = Symbol('key') //可选的字符串key

//Symbol的值时唯一的
const s1 = Symbol()
const s2 = Symbol()
// console.log(s1 === s2);  // false

//用作对象属性的键
let val = Symbol();
let obj = {
  [val]: 'value'
}
console.log(obj[val]);  //"value"

//使用sym定义的属性是不能够通过以下方式进行遍历的
let symbol1 = Symbol(666)
let symbol2 = Symbol(777)
const obje = {
  [symbol1]: 'niaho',
  [symbol2]: 678,
  age: 90,
  sex: '男'
}
//for in 遍历
for (const key in obje) {
  console.log(key);
}
//Object.keys 遍历
Object.keys(obje)
console.log(Object.keys(obje));
//通过getOwnPropertyNames进行遍历 还是拿不到symbol
Object.getOwnPropertyNames(obje)
//JSON.stringify方法
JSON.stringify(obje)
//如何拿到
Object.getOwnPropertySymbols(obje)
Reflect.ownKeys(obje)

// Symbol.iterator迭代器和生成器
let arr = [1, 2, 3, 4]
let iterator = arr[Symbol.iterator]()
console.log(iterator.next()); //{ value: 1, done: false }
console.log(iterator.next()); //{ value: 2, done: false }
console.log(iterator.next()); //{ value: 3, done: false }
console.log(iterator.next()); //{ value: 4, done: false }
console.log(iterator.next()); //{ value: undefined, done: true }

//测试用例
interface Item {
  age: number
  name: string
}
const array: Array<Item> = [{ age: 3, name: 'zhou' }, { age: 5, name: 'liu' }, { age: 9, name: 'zhang' }]
type mapTypes = string | number
const map: Map<mapTypes, mapTypes> = new Map()
map.set('1', '王爷')
map.set('2', '少爷')
const obj1 = {
  aaa: 111,
  bbb: 222
}
let set: Set<number> = new Set([1, 2, 3, 4, 5, 6])
const gen = (erg: any): void => {
  let it: Iterator<any> = erg[Symbol.iterator]()
  let next: any = { done: false }
  while (!next.done) {
    next = it.next()
    if (!next.done) {
      console.log(next.value);
    }
  }
}
gen(array)

// 以下为这些symbols的列表：
// Symbol.hasInstance
// 方法，会被instanceof运算符调用。构造器对象用来识别一个对象是否是其实例。
// Symbol.isConcatSpreadable
// 布尔值，表示当在一个对象上调用Array.prototype.concat时，这个对象的数组元素是否可展开。
// Symbol.iterator
// 方法，被for - of语句调用。返回对象的默认迭代器。
// Symbol.match
// 方法，被String.prototype.match调用。正则表达式用来匹配字符串。
// Symbol.replace
// 方法，被String.prototype.replace调用。正则表达式用来替换字符串中匹配的子串。
// Symbol.search
// 方法，被String.prototype.search调用。正则表达式返回被匹配部分在字符串中的索引。
// Symbol.species
// 函数值，为一个构造函数。用来创建派生对象。
// Symbol.split
// 方法，被String.prototype.split调用。正则表达式来用分割字符串。
// Symbol.toPrimitive
// 方法，被ToPrimitive抽象操作调用。把对象转换为相应的原始值。
// Symbol.toStringTag
// 方法，被内置方法Object.prototype.toString调用。返回创建对象时默认的字符串描述。
// Symbol.unscopables
// 对象，它自己拥有的属性会被with作用域排除在外。
